/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "obsidian_sanctum.h"
#include "Player.h"

class instance_obsidian_sanctum : public InstanceMapScript
{
public:
    instance_obsidian_sanctum() : InstanceMapScript("instance_obsidian_sanctum", 615) { }

    InstanceScript* GetInstanceScript(InstanceMap* pMap) const
    {
        return new instance_obsidian_sanctum_InstanceMapScript(pMap);
    }

	struct instance_obsidian_sanctum_InstanceMapScript : public InstanceScript
	{
		instance_obsidian_sanctum_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {}

		uint64 m_uiSartharionGUID;
		uint64 m_uiTenebronGUID;
		uint64 m_uiShadronGUID;
		uint64 m_uiVesperonGUID;
		uint32 Encounters[MAX_ENCOUNTERS];
		uint64 m_uiPortalGUID;
		uint8 portalCount;

		void Initialize()
		{
			m_uiSartharionGUID = 0;
			m_uiTenebronGUID   = 0;
			m_uiShadronGUID    = 0;
			m_uiVesperonGUID   = 0;
			m_uiPortalGUID     = 0;
			portalCount        = 0;
			memset(&Encounters, 0, sizeof(Encounters));
		};

		void OnCreatureCreate(Creature* pCreature)
		{
			switch(pCreature->GetEntry())
			{
				case NPC_SARTHARION:
					m_uiSartharionGUID = pCreature->GetGUID();
					break;
				case NPC_TENEBRON:
					m_uiTenebronGUID = pCreature->GetGUID();
					break;
				case NPC_SHADRON:
					m_uiShadronGUID = pCreature->GetGUID();
					break;
				case NPC_VESPERON:
					m_uiVesperonGUID = pCreature->GetGUID();
					break;
			}
		}

		uint32 GetData(uint32 id) const
		{
			switch (id)
			{
				case BOSS_SARTHARION_EVENT:
				case BOSS_TENEBRON_EVENT:
				case BOSS_SHADRON_EVENT:
				case BOSS_VESPERON_EVENT:
					return Encounters[id];
			}

			return 0;
		}

		uint64 GetData64(uint32 uiData) const
		{
			switch(uiData)
			{
				case DATA_SARTHARION:
					return m_uiSartharionGUID;
				case DATA_TENEBRON:
					return m_uiTenebronGUID;
				case DATA_SHADRON:
					return m_uiShadronGUID;
				case DATA_VESPERON:
					return m_uiVesperonGUID;
			}
			return 0;
		}

		bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0)
		{
			switch(criteria_id)
			{
				// Gonna Go When the Volcano Blows (10 player) (2047)
				case 7326:
				// Gonna Go When the Volcano Blows (25 player) (2048)
				case 7327:
					if (Creature* cr = instance->GetCreature(m_uiSartharionGUID))
						if (!cr->AI()->GetData(source->GetGUIDLow()))
							return true;
					break;
				// Less Is More (10 player) (624)
				case 7189:
				case 7190:
				case 7191:
				case 522:
					if (instance->GetPlayersCountExceptGMs() < 9)
						return true;
					break;
				// Less Is More (25 player) (1877)
				case 7185:
				case 7186:
				case 7187:
				case 7188:
					if (instance->GetPlayersCountExceptGMs() < 21)
						return true;
					break;
				// Twilight Assist (10 player) (2049)
				case 7328:
				// Twilight Assist (25 player) (2052)
				case 7331:
					if (Creature* cr = instance->GetCreature(m_uiSartharionGUID))
						if (cr->AI()->GetData(DATA_ACHIEVEMENT_DRAGONS_COUNT) >= 1)
							return true;
					break;
				// Twilight Duo (10 player) (2050)
				case 7329:
				// Twilight Duo (25 player) (2053)
				case 7332:
					if (Creature* cr = instance->GetCreature(m_uiSartharionGUID))
						if (cr->AI()->GetData(DATA_ACHIEVEMENT_DRAGONS_COUNT) >= 2)
							return true;
					break;
				// Twilight Zone (10 player) (2051)
				case 7330:
				// Twilight Zone (25 player) (2054)
				case 7333:
					if (Creature* cr = instance->GetCreature(m_uiSartharionGUID))
						if (cr->AI()->GetData(DATA_ACHIEVEMENT_DRAGONS_COUNT) >= 3)
							return true;
					break;
				
			}
			return false;
		}

		void SetData(uint32 type, uint32 data)
		{
			switch(type)
			{
				case BOSS_SARTHARION_EVENT:
				case BOSS_TENEBRON_EVENT:
				case BOSS_SHADRON_EVENT:
				case BOSS_VESPERON_EVENT:
					Encounters[type] = data;
					break;
				case DATA_ADD_PORTAL:
					if (!m_uiPortalGUID)
					{
						if (Creature* cr = instance->GetCreature(m_uiSartharionGUID))
							if (GameObject* go = cr->SummonGameObject(GO_TWILIGHT_PORTAL, 3247.29f, 529.804f, 58.9595f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
							{
								cr->RemoveGameObject(go, false);
								m_uiPortalGUID = go->GetGUID();
							}

						portalCount = 0;
					}

					portalCount++;
					break;
				case DATA_CLEAR_PORTAL:
					portalCount--;
					if (!portalCount || data == 2)
					{
						if (GameObject* go = instance->GetGameObject(m_uiPortalGUID))
							go->Delete();

						DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_SHIFT);
						m_uiPortalGUID = 0;
					}
					break;
			}

			if (data == DONE)
				SaveToDB();
		}

		std::string GetSaveData()
        {
            OUT_SAVE_INST_DATA;

            std::ostringstream saveStream;
            saveStream << "O S " << Encounters[0] << ' ' << Encounters[1] << ' ' << Encounters[2] << ' ' << Encounters[3];

            OUT_SAVE_INST_DATA_COMPLETE;
            return saveStream.str();
        }
			
		void Load(const char* strIn)
		{
			if (!strIn)
			{
				OUT_LOAD_INST_DATA_FAIL;
				return;
			}

			OUT_LOAD_INST_DATA(strIn);

			char dataHead1, dataHead2;

			std::istringstream loadStream(strIn);
			loadStream >> dataHead1 >> dataHead2;

			if (dataHead1 == 'O' && dataHead2 == 'S')
			{
				for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
				{
					loadStream >> Encounters[i];
					if (Encounters[i] == IN_PROGRESS)
						Encounters[i] = NOT_STARTED;
				}
			}

			OUT_LOAD_INST_DATA_COMPLETE;
		}
	};
};

void AddSC_instance_obsidian_sanctum()
{
    new instance_obsidian_sanctum();
}
